#include "../kernel/vsprintf.c"
#include "test.h"

void test_vsprintf_number_dec(void **state)
{
    char str[64] = {0};
    char *end_str = NULL;
    int ret;
    int base = 10;

    end_str = number(str, 123, base, 0, 2, 0);
    ret = memcmp(str, "123", end_str - str);
    assert_int_equal(ret, 0);

    /* 右对齐 空格填充 */
    end_str = number(str, 123, base, 5, 2, 0);
    ret = memcmp(str, "  123", end_str - str);
    assert_int_equal(ret, 0);

    /* 右对齐 0填充 */
    end_str = number(str, 123, base, 5, 2, ZEROPAD);
    ret = memcmp(str, "00123", end_str - str);
    assert_int_equal(ret, 0);

    /* 左对齐 空格填充 */
    end_str = number(str, 123, base, 5, 2, LEFT);
    ret = memcmp(str, "123  ", end_str - str);
    assert_int_equal(ret, 0);

    /* 左对齐 0填充（实际不会填充0，仍然以空格填充） */
    end_str = number(str, 123, base, 5, 2, LEFT | ZEROPAD);
    ret = memcmp(str, "123  ", end_str - str);
    assert_int_equal(ret, 0);

    /* 左对齐，空格填充，精度超过数值长度（精度超出长度的部分，会在左边补零） */
    end_str = number(str, 123, base, 5, 4, LEFT);
    ret = memcmp(str, "0123 ", end_str - str);
    assert_int_equal(ret, 0);

    /* 负数，左对齐，空格填充 */
    end_str = number(str, -123, base, 6, 4, SIGN | LEFT);
    ret = memcmp(str, "-0123 ", end_str - str);
    assert_int_equal(ret, 0);

    /* 实际负数，但是未传入符号标记 */
    end_str = number(str, -1, base, 0, 0, 0);
    ret = memcmp(str, "4294967295", end_str - str);
    assert_int_equal(ret, 0);
}

void test_vsprintf_number_hex(void **state)
{
    char str[64] = {0};
    char *end_str = NULL;
    int ret;
    int base = 16;

    end_str = number(str, 0x12AB, base, 0, 2, SMALL);
    ret = memcmp(str, "12ab", end_str - str);
    assert_int_equal(ret, 0);

    end_str = number(str, 0x12AB, base, 0, 2, 0);
    ret = memcmp(str, "12AB", end_str - str);
    assert_int_equal(ret, 0);

    end_str = number(str, 0x12AB, base, 10, 6, SPECIAL | LEFT);
    ret = memcmp(str, "0X0012AB  ", end_str - str);
    assert_int_equal(ret, 0);

    end_str = number(str, 0x12AB, base, 10, 6, SPECIAL | SMALL);
    ret = memcmp(str, "  0x0012ab", end_str - str);
    assert_int_equal(ret, 0);
}

static int call_vnsprintf(char *str, const char *fmt, ...)
{
    va_list args;
    int i;
    va_start(args, fmt);
    i = vsprintf(str, fmt, args);
    va_end(args);
    return i;
}

void test_vsprintf(void **state)
{
    char str[64] = {0};
    int ret, len;
    int p;

    len = call_vnsprintf(str, "%-5.2d add %4.2d is %d", -1, 1, 0);
    ret = memcmp(str, "-01   add   01 is 0", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The Key is %c", 'W');
    ret = memcmp(str, "The Key is W", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The Key string is %s", "linux");
    ret = memcmp(str, "The Key string is linux", len);
    assert_int_equal(ret, 0);

    p = 0x12AB;
    len = call_vnsprintf(str, "The pointer is %p", (void*)p);
    ret = memcmp(str, "The pointer is 000012AB", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The hex is %-0#12.8X", 0x12ab);
    ret = memcmp(str, "The hex is 0X000012AB  ", len);
    assert_int_equal(ret, 0);
}

void test_vsprintf_ex(void **state)
{
    char str[64] = {0};
    int ret, len;

    len = call_vnsprintf(str, "The dec is %-*.4d", 6, 123);
    ret = memcmp(str, "The dec is 0123  ", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The dec is %*.4d", -6, 123);
    ret = memcmp(str, "The dec is 0123  ", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The dec is %6.*d", 4, 123);
    ret = memcmp(str, "The dec is   0123", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The dec is %6.*d", -4, 123);
    ret = memcmp(str, "The dec is    123", len);
    assert_int_equal(ret, 0);

    len = call_vnsprintf(str, "The hex is %0#*.*X", -12, 8, 0x12ab);
    ret = memcmp(str, "The hex is 0X000012AB  ", len);
    assert_int_equal(ret, 0);
}